﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Money.Plugins;

namespace Money.Interface
{
    // TODO graph does not handle being opened closed and then reopened. The graph fails at that point?
    public partial class ChartFramework : Form
    {
        private DateTime _startDate;
        private DateTime _endDate;

        private Graphs _graphs = new Graphs();
        private UserControl _graphControl = null;

        private IDataSet _dataInterface = null;

        private Money.Plugins.IGraph _graph = null;

        private TransactionFilter _filterDelegate;
        public TransactionFilter FilterDelegate 
        {
            get { return _filterDelegate; }
            set 
            { 
                _filterDelegate = value;
            }
        }

        public ChartFramework(IDataSet dataInterface)
        {
            InitializeComponent();

            _dataInterface = dataInterface;

            var startDate = (from t in _dataInterface.Transactions select t.Date).Min();
            var endDate = (from t in _dataInterface.Transactions select t.Date).Max();

            _startDate = startDate;
            _endDate = endDate;

            TimeSpan timeSpan = endDate - startDate;

            _chartTypeSelection.Items.Clear();
            foreach (Money.Plugins.IGraph graphPlugin in PluginHost.GraphPlugins)
            {
                _chartTypeSelection.Items.Add(graphPlugin.Name);
            }

            // TODO this is disabled at present as we dont have an idea of what this should be yet
            //_chartTypeSelection.Items.Add("Spending by Sub-category");

            if (_chartTypeSelection.Items.Count > 0)
            {
                _chartTypeSelection.SelectedIndex = 0;
            }

            DisplayChart();
        }

        private void DisplayChart()
        {
            string displayChart = _chartTypeSelection.SelectedItem.ToString();
            Money.Plugins.IGraph graph = _graphs.GetGraph(displayChart);

            if(graph != null)
            {
                _graph = graph;

                _graphControl = _graph.MainControl;
                _graph.SetDataInterface(_dataInterface);

                if (_enableFilter.Checked)
                {
                    _graph.ApplyFilter += new FilterEventHandler(_graph_ApplyFilter);
                }
                else
                {
                    _graph.ApplyFilter -= _graph_ApplyFilter;
                }

                _panel.Controls.Clear();
                _panel.Controls.Add(_graphControl);

                _graphControl.Anchor = (AnchorStyles)(AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right);

                // _graph.Name = "graph";

                _graphControl.Location = new System.Drawing.Point(0, 0);
                _graphControl.Size = _panel.ClientSize;

                _graphControl.TabIndex = 0;

                // Force a redraw of the graph
                Money.Plugins.DateChangedEventArgs dateEventArgs = new Money.Plugins.DateChangedEventArgs();
                dateEventArgs.StartDate = _startDate;
                dateEventArgs.EndDate = _endDate;
                _graph.UpdateGraph(this, dateEventArgs);
            }
        }

        void _graph_ApplyFilter(object sender, FilterEventArgs filter)
        {
            TransactionMatchRule filterRule = new TransactionMatchRule();

            filterRule.EndDate = filter.EndDate;
            filterRule.StartDate = filter.StartDate;
            if (String.IsNullOrWhiteSpace(filter.Category))
            {
                filterRule.CategoryId = null;
            }
            else
            {
                filterRule.CategoryId = Categories.CategoryList.GetCategoryId(filter.Category);
            }
            if (String.IsNullOrWhiteSpace(filter.CategoryGroup))
            {
                filterRule.CategoryGroupId = null;
            }
            else
            {
                filterRule.CategoryGroupId = Categories.CategoryList.GetCategoryId(filter.CategoryGroup);
            }
            filterRule.Account = filter.Account;

            if (_filterDelegate != null)
            {
                _filterDelegate(filterRule);
            }
        }

        private void cbChartType_SelectionChangeCommitted(object sender, EventArgs e)
        {
        }

        private void cbChartType_SelectedIndexChanged(object sender, EventArgs e)
        {
            DisplayChart();
        }

        private void panel1_Resize(object sender, EventArgs e)
        {
            if (_graph != null)
            {
                _graphControl.Size = _panel.ClientSize;
            }
        }

        private void _enableFilter_Click(object sender, EventArgs e)
        {
            if (_graph != null)
            {
                if (_enableFilter.Checked == false)
                {
                    _graph.ApplyFilter -= _graph_ApplyFilter;

                    if (FilterDelegate != null)
                    {
                        TransactionMatchRule rule = new TransactionMatchRule();
                        // clear filter that is applied
                        FilterDelegate(rule);
                    }
                }
                else
                {
                    _graph.ApplyFilter += new FilterEventHandler(_graph_ApplyFilter);
                }
            }
        }

        private void Chart_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Escape:
                    _graph.ResetGraph();
                    break;
            }
        }

        public void SetDataInterface(IDataSet dataInterface)
        {
            _dataInterface = dataInterface;
        }

        private void ChartFramework_FormClosing(object sender, FormClosingEventArgs e)
        {
            // HACK to stop exceptions at present we only hide the form
            e.Cancel = true;
            this.Visible = false;
        }
    }
}
